package com.acxy.ants.core.plugin.entity;

import com.acxy.ants.common.kit.StrCaseKit;
import com.acxy.ants.core.IBean;
import com.acxy.ants.core.kit.LogKit;
import com.acxy.ants.core.plugin.db.Db;
import com.acxy.ants.resful.bean.Page;
import com.alibaba.fastjson.JSON;

import java.util.List;

/**
 * @author MrShun
 * @version 1.0
 * @Date 2017-09-06
 */
public class Model extends IBean{

    private SqlParams sqlParams;

    //缓存时间
    private Long cacheTime = null;

    public Model() {
        sqlParams = new SqlParams();
    }

    public Long saveReturnKey(Db db) {
        SqlParams sql = SqlParamsKit.getSql(Symbol.INSERT, this);
        return db.insertReturnKey(sql.getSql(), sql.getParams());
    }

    public void save(Db db) {
        SqlParams sql = SqlParamsKit.getSql(Symbol.INSERT, this);
        db.insert(sql.getSql(), sql.getParams());
    }

    public int delete(Db db) {
        SqlParams sql = SqlParamsKit.getSql(Symbol.DELETE, this);
        return db.delete(sql.getSql(), sql.getParams());
    }

    public int deleteById(Db db, Object id) {
        SqlParams sql = SqlParamsKit.getSql(Symbol.DELETE, this, id);
        return db.delete(sql.getSql(), sql.getParams());
    }

    public Long count(Db db) {
        SqlParams sql = SqlParamsKit.getSql(Symbol.COUNT, this);
        return db.query(sql.getSql(), sql.getParams()).getLong("count");
    }

    public <T extends Model> T find(Db db) {
        SqlParams sql = SqlParamsKit.getSql(Symbol.SELECT, this);
        if (cacheTime == null) return db.query(sql.getSql(), (T) this, sql.getParams());
        String key = sql.getCacheKey();
        if (CacheManager.expire(key)) {
            T obj = db.query(sql.getSql(), (T) this, sql.getParams());
            CacheManager.put(key, new Cache(obj, cacheTime));
            LogKit.debug("[{}] 无缓存信息存放缓存对象...", key);
            return obj;
        } else {
            LogKit.debug("[{}] 检测到缓存信息直接放回对象...", key);
            return (T) CacheManager.get(key);
        }
    }

    public <T extends Model> List<T> list(Db db) {
        SqlParams sql = SqlParamsKit.getSql(Symbol.SELECT, this);
        if (cacheTime == null) return db.list(sql.getSql(), (Class<T>) getClass(), sql.getParams());
        String key = sql.getCacheKey();
        if (CacheManager.expire(key)) {
            List<T> obj = db.list(sql.getSql(), (Class<T>) getClass(), sql.getParams());
            CacheManager.put(key, new Cache(obj, cacheTime));
            LogKit.debug("[{}] 无缓存信息存放缓存对象...", key);
            return obj;
        } else {
            LogKit.debug("[{}] 检测到缓存信息直接放回对象...", key);
            return (List<T>) CacheManager.get(key);
        }
    }

    public int update(Db db) {
        SqlParams sql = SqlParamsKit.getSql(Symbol.UPDATE, this);
        return db.update(sql.getSql(), sql.getParams());
    }

    public Page page(Db db, int index, int size) {
        if (!"".equals(sqlParams.getLimitStr())) throw new RuntimeException("分页 page() 之前不能使用 limit() 方法!");
        SqlParams sql = SqlParamsKit.getSql(Symbol.SELECT, this);
        if (cacheTime == null) return db.page(sql.getSql(), getClass(), index, size, sql.getParams());
        String key = sql.getCacheKey();
        if (CacheManager.expire(key)) {
            Page obj = db.page(sql.getSql(), getClass(), index, size, sql.getParams());
            CacheManager.put(key, new Cache(obj, cacheTime));
            LogKit.debug("[{}] 无缓存信息存放缓存对象...", key);
            return obj;
        } else {
            LogKit.debug("[{}] 检测到缓存信息直接放回对象...", key);
            return (Page) CacheManager.get(key);
        }
    }


    public <T extends Model> T and(String key, Object value) {
        return and(key, null, value);
    }

    public <T extends Model> T and(String key, String symbol, Object value) {
        key = StrCaseKit.toUnderlineName(key);
        if (symbol == null)
            sqlParams.addCondition("and " + key + "=? ");
        else
            sqlParams.addCondition("and " + key + symbol + "? ");
        sqlParams.addValue(value);
        return (T) this;
    }

    public <T extends Model> T or(String key, Object value) {
        return or(key, null, value);
    }

    public <T extends Model> T or(String key, String symbol, Object value) {
        key = StrCaseKit.toUnderlineName(key);
        if (symbol == null)
            sqlParams.addCondition("or " + key + "=? ");
        else
            sqlParams.addCondition("or " + key + symbol + "? ");
        sqlParams.addValue(value);
        return (T) this;
    }

    public <T extends Model> T search(String key, Object value) {
        return search(key, value, Symbol.CENTER);
    }

    public <T extends Model> T search(String key, Object value, Symbol symbol) {
        key = StrCaseKit.toUnderlineName(key);
        if (symbol == Symbol.LEFT)
            sqlParams.addCondition("and " + key + " like concat(?,'%') ");
        else if (symbol == Symbol.RIGHT)
            sqlParams.addCondition("and " + key + " like concat('%', ?) ");
        else
            sqlParams.addCondition("and " + key + " like concat(concat('%',?),'%') ");
        sqlParams.addValue(value);
        return (T) this;
    }

    public <T extends Model> T orderBy(String key, Symbol symbol) {
        key = StrCaseKit.toUnderlineName(key);
        if (symbol == Symbol.ASC)
            sqlParams.setOrderByStr(" order by " + key + " asc ");
        else if (symbol == Symbol.DESC)
            sqlParams.setOrderByStr(" order by " + key + " desc ");
        return (T) this;
    }

    public <T extends Model> T orderBy(String key, String symbol){
        if(symbol == null || "".equals(symbol)) return (T) this;
        if(symbol.equalsIgnoreCase(String.valueOf(Symbol.DESC)))
            return orderBy(key, Symbol.DESC);
        else if(symbol.equalsIgnoreCase(String.valueOf(Symbol.ASC)))
            return orderBy(key, Symbol.ASC);
        return (T) this;
    }

    public <T extends Model> T limit(Integer start, Integer size) {
        if (start == null) {
            sqlParams.setLimitStr(" limit " + size);
            sqlParams.addValue(size);
        }else {
            sqlParams.setLimitStr(" limit " + start + "," + size);
            sqlParams.addValue(start);
            sqlParams.addValue(size);
        }
        return (T) this;
    }

    public <T extends Model> T limit(int rows) {
        return limit(null, rows);
    }

    public <T extends Model> T label(String label) {
        sqlParams.setLabelStr(label);
        return (T) this;
    }

    public <T extends Model> T leftJoin(String leftJoinStr) {
        sqlParams.setLeftJoinStr(leftJoinStr);
        return (T) this;
    }

    //where拼接 当实体有主键id的时候
    //id一定需要最后面例如 where("anccount=? and id=?")
    public <T extends Model> T where(String whereStr) {
        sqlParams.setWhereStr(" where " + whereStr);
        return (T) this;
    }

    public SqlParams sqlParamsObject() {
        return sqlParams;
    }

    public <T extends Model> T cache(long time) {
        this.cacheTime = time * 1000;
        return (T) this;
    }
}
